class Dependency {
  constructor() {
    this.depSubs = [] // 依赖的下级
    this.notifSubs = [] // 通知的下级
  }

  addSubDep(dep) {
    if (dep.isSubDep(this)) throw new Error('dependency confusion')
    if (!this.depSubs.includes(dep)) this.depSubs.push(dep)
  }
  /** 参数传入的 dep 是否是下级 */
  isSubDep(dep) {
    return this.depSubs.includes(dep)
  }

  refreshNotif() {
    this.notifSubs = []
    const subLen = this.depSubs.length
    if (subLen <= 0) return

    const subs = [...this.depSubs]

    for (let idx1 = 0; idx1 < subLen; idx1++) {
      let sub1 = subs[idx1]
      if (!sub1) continue

      for (let idx2 = idx1 + 1; idx2 < subLen; idx2++) {
        const sub2 = subs[idx2]
        if (!sub2) continue

        if (sub1.isSubDep(sub2)) subs[idx2] = null
        else if (sub2.isSubDep(sub1)) {
          sub1 = subs[idx1] = null
          break
        }
      }

      if (sub1) this.notifSubs.push(sub1)
    }

    for (const sub of this.notifSubs) {
      sub.refreshNotif()
    }
  }

  /** 通知所有下级 */
  notify() {
    for (const sub of this.notifSubs) {
      sub.onNotif()
      sub.notify()
    }
  }

  /** 接收到通知 */
  onNotif() {}
}

class Reactive extends Dependency {
  constructor() {
    super()
  }
  onNotif() {
    console.log(this)
  }
}

const p = new Proxy([1, 2, 3], {
  get: function (arr, key) {
    console.log(`Calculate get: `, arr, key)
    return key + 100
  },
  set: function (arr, key, value) {
    arr[key] = value
    console.log(key, value)
    return true
  },
  apply: function (target, thisArg, argumentsList) {
    console.log(`Calculate apply: `, target, thisArg, argumentsList)
    // Expected output: "Calculate sum: 1,2"

    return null
  }
})

console.log('kkkkkkk 1111')
console.log(p)
p.push(44)
console.log(p[1])

setTimeout(() => {
  console.log('kkkkkkkkkkkkkkk')

  const r1 = new Reactive()
  const r2 = new Reactive()
  const r3 = new Reactive()
  const r4 = new Reactive()
  const r5 = new Reactive()
  const r6 = new Reactive()
  const r7 = new Reactive()
  const r8 = new Reactive()

  const r10 = new Reactive()

  r1.id = 'r1'
  r2.id = 'r2'
  r3.id = 'r3'
  r4.id = 'r4'
  r5.id = 'r5'
  r6.id = 'r6'
  r7.id = 'r7'
  r8.id = 'r8'
  r10.id = 'r10'

  r1.addSubDep(r2)

  r1.addSubDep(r2)
  r1.addSubDep(r3)
  r1.addSubDep(r4)
  r1.addSubDep(r5)
  r1.addSubDep(r6)
  r1.addSubDep(r7)

  r2.addSubDep(r4)
  r2.addSubDep(r10)

  r6.addSubDep(r2)

  r1.refreshNotif()
  console.log(r1)

  console.log('kkkkkkkkkkkkkkk notify')
  r1.notify()
}, 100)
